﻿using Amazon.S3.Model;
using Amazon.S3;

namespace Files_Upload.API
{
    /// <summary>
    /// miniio 的分片上传封装，采用了AWSSDK.S3的SDK，该SDK是兼容了亚马逊s3的接口api，而minio是采用亚马逊s3的api模式
    /// </summary>
    public class MinioHelper
    {

        private IAmazonS3 amazonS3Client;

        public MinioHelper(IAmazonS3 amazonS3Client)
        {
            this.amazonS3Client = amazonS3Client;
        }

        /// <summary>
        /// 初始化文件获取uploadid
        /// </summary>
        /// <param name="BucketName">桶名称</param>
        /// <param name="KeyName">存储文件的桶路径</param>
        /// <returns>返回uploadID</returns>
        public async Task<string> InitMultipartChunkUploadFile(string BucketName, string KeyName)
        {
            InitiateMultipartUploadRequest initRequest = new InitiateMultipartUploadRequest
            {
                BucketName = BucketName,
                Key = KeyName,
            };
            InitiateMultipartUploadResponse initResponse = await amazonS3Client.InitiateMultipartUploadAsync(initRequest);
            return initResponse.UploadId;
        }
        /// <summary>
        /// 上传分片，这是看minio web控制台是看不出来分片文件的，需要去minio存储文件夹下的.minio.sys/multipart查看
        /// </summary>
        /// <param name="BucketName">桶名称</param>
        /// <param name="KeyName">存储文件的桶路径</param>
        /// <param name="UploadId">uploadID</param>
        /// <param name="ChunkCount">当前第几片</param>
        /// <param name="PartSize">当前分片大小</param>
        /// <param name="ChunkFile">分片文件</param>
        /// <returns>返回etag和当前第几片</returns>
        public async Task<PartETag> ChunkUploadAsync(string BucketName, string KeyName, string UploadId, int ChunkCount, long PartSize, Stream ChunkFile)
        {
            UploadPartRequest uploadRequest = new UploadPartRequest();
            uploadRequest.BucketName = BucketName;
            uploadRequest.Key = KeyName;
            uploadRequest.UploadId = UploadId;
            uploadRequest.PartNumber = ChunkCount;
            uploadRequest.InputStream = ChunkFile;
            uploadRequest.PartSize = PartSize;
            //进行分片上传
            UploadPartResponse up1Response = await amazonS3Client.UploadPartAsync(uploadRequest);
            return new PartETag { ETag = up1Response.ETag, PartNumber = ChunkCount };
        }
        /// <summary>
        /// 合并分片为整个文件，合并后minio存储的文件夹里.minio.sys/multipart下该文件会删除
        /// </summary>
        /// <param name="BucketName">桶名称</param>
        /// <param name="KeyName">存储文件的桶路径</param>
        /// <param name="UploadId">uploadID</param>
        /// <param name="partETags">当前第几片</param>
        /// <returns>返回存储的Key属性字段的相对路径(location是绝对路径，该属性不可取，如果服务器迁移会使人崩溃！)</returns>

        public async Task<CompleteMultipartUploadResponse> CompleteMultipartUploadFile(string BucketName, string KeyName, string UploadId, List<PartETag> partETags)
        {
            CompleteMultipartUploadRequest compRequest = new CompleteMultipartUploadRequest
            {
                BucketName = BucketName,
                Key = KeyName,
                UploadId = UploadId,
                PartETags = partETags,
            };
            CompleteMultipartUploadResponse compResponse = await amazonS3Client.CompleteMultipartUploadAsync(compRequest);
            return compResponse;
        }

        /// <summary>
        /// 查询该uploadID已上传了几个分片详细信息
        /// </summary>
        /// <param name="BucketName">桶名称</param>
        /// <param name="KeyName">存储文件的桶路径</param>
        /// <param name="UploadId">uploadID</param>
        /// <returns>只需要返回值数组下每个对象里的eTag和partNumber</returns>
        public async Task<List<PartDetail>> ListPartsUploadInfo(string BucketName, string KeyName, string UploadId)
        {
            ListPartsRequest listPartRequest = new ListPartsRequest
            {
                BucketName = BucketName,
                Key = KeyName,
                UploadId = UploadId
            };
            ListPartsResponse listPartResponse = await amazonS3Client.ListPartsAsync(listPartRequest);
            return listPartResponse.Parts;
        }
    }

}
